package com.arcbees.test.collaborative.shared.diffsync;

import java.util.LinkedList;
import java.util.List;

import com.arcbees.test.collaborative.client.collaborativetext.CursorOffset;

public interface DiffMatchPatch {

  /**
   * Find the differences between two texts. Run a faster, slightly less optimal
   * diff. This method allows the 'checklines' of diff_main() to be optional.
   * Most of the time checklines is wanted, so default to true.
   * 
   * @param text1 Old string to be diffed.
   * @param text2 New string to be diffed.
   * @return Linked List of Diff objects.
   */
  LinkedList<Diff> diff_main(String text1, String text2);

  /**
   * Find the differences between two texts.
   * 
   * @param text1 Old string to be diffed.
   * @param text2 New string to be diffed.
   * @param checklines Speedup flag. If false, then don't run a line-level diff
   *          first to identify the changed areas. If true, then run a faster
   *          slightly less optimal diff.
   * @return Linked List of Diff objects.
   */
  LinkedList<Diff> diff_main(String text1, String text2, boolean checklines);

  /**
   * Determine the common prefix of two strings
   * 
   * @param text1 First string.
   * @param text2 Second string.
   * @return The number of characters common to the start of each string.
   */
  int diff_commonPrefix(String text1, String text2);

  /**
   * Determine the common suffix of two strings
   * 
   * @param text1 First string.
   * @param text2 Second string.
   * @return The number of characters common to the end of each string.
   */
  int diff_commonSuffix(String text1, String text2);

  /**
   * Reduce the number of edits by eliminating semantically trivial equalities.
   * 
   * @param diffs LinkedList of Diff objects.
   */
  void diff_cleanupSemantic(LinkedList<Diff> diffs);

  /**
   * Look for single edits surrounded on both sides by equalities which can be
   * shifted sideways to align the edit to a word boundary. e.g: The c<ins>at
   * c</ins>ame. -> The <ins>cat </ins>came.
   * 
   * @param diffs LinkedList of Diff objects.
   */
  void diff_cleanupSemanticLossless(LinkedList<Diff> diffs);

  /**
   * Reduce the number of edits by eliminating operationally trivial equalities.
   * 
   * @param diffs LinkedList of Diff objects.
   */
  void diff_cleanupEfficiency(LinkedList<Diff> diffs);

  /**
   * Reorder and merge like edit sections. Merge equalities. Any edit section
   * can move as long as it doesn't cross an equality.
   * 
   * @param diffs LinkedList of Diff objects.
   */
  void diff_cleanupMerge(LinkedList<Diff> diffs);

  /**
   * loc is a location in text1, compute and return the equivalent location in
   * text2. e.g. "The cat" vs "The big cat", 1->1, 5->8
   * 
   * @param diffs LinkedList of Diff objects.
   * @param loc Location within text1.
   * @return Location within text2.
   */
  int diff_xIndex(LinkedList<Diff> diffs, int loc);

  /**
   * Convert a Diff list into a pretty HTML report.
   * 
   * @param diffs LinkedList of Diff objects.
   * @return HTML representation.
   */
  String diff_prettyHtml(LinkedList<Diff> diffs);

  /**
   * Compute and return the source text (all equalities and deletions).
   * 
   * @param diffs LinkedList of Diff objects.
   * @return Source text.
   */
  String diff_text1(LinkedList<Diff> diffs);

  /**
   * Compute and return the destination text (all equalities and insertions).
   * 
   * @param diffs LinkedList of Diff objects.
   * @return Destination text.
   */
  String diff_text2(LinkedList<Diff> diffs);

  /**
   * Compute the Levenshtein distance; the number of inserted, deleted or
   * substituted characters.
   * 
   * @param diffs LinkedList of Diff objects.
   * @return Number of changes.
   */
  int diff_levenshtein(LinkedList<Diff> diffs);

  /**
   * Crush the diff into an encoded string which describes the operations
   * required to transform text1 into text2. E.g. =3\t-2\t+ing -> Keep 3 chars,
   * delete 2 chars, insert 'ing'. Operations are tab-separated. Inserted text
   * is escaped using %xx notation.
   * 
   * @param diffs Array of diff tuples.
   * @return Delta text.
   */
  String diff_toDelta(LinkedList<Diff> diffs);

  /**
   * Given the original text1, and an encoded string which describes the
   * operations required to transform text1 into text2, compute the full diff.
   * 
   * @param text1 Source string for the diff.
   * @param delta Delta text.
   * @return Array of diff tuples or null if invalid.
   * @throws IllegalArgumentException If invalid input.
   */
  LinkedList<Diff> diff_fromDelta(String text1, String delta)
      throws IllegalArgumentException;

  /**
   * Locate the best instance of 'pattern' in 'text' near 'loc'. Returns -1 if
   * no match found.
   * 
   * @param text The text to search.
   * @param pattern The pattern to search for.
   * @param loc The location to search around.
   * @return Best match index or -1.
   */
  int match_main(String text, String pattern, int loc);

  /**
   * Compute a list of patches to turn text1 into text2. A set of diffs will be
   * computed.
   * 
   * @param text1 Old text.
   * @param text2 New text.
   * @return LinkedList of Patch objects.
   */
  LinkedList<Patch> patch_make(String text1, String text2);

  /**
   * Compute a list of patches to turn text1 into text2. text1 will be derived
   * from the provided diffs.
   * 
   * @param diffs Array of diff tuples for text1 to text2.
   * @return LinkedList of Patch objects.
   */
  LinkedList<Patch> patch_make(LinkedList<Diff> diffs);

  /**
   * Compute a list of patches to turn text1 into text2. text2 is ignored, diffs
   * are the delta between text1 and text2.
   * 
   * @param text1 Old text
   * @param text2 Ignored.
   * @param diffs Array of diff tuples for text1 to text2.
   * @return LinkedList of Patch objects.
   * @deprecated Prefer patch_make(String text1, LinkedList<Diff> diffs).
   */
  LinkedList<Patch> patch_make(String text1, String text2,
      LinkedList<Diff> diffs);

  /**
   * Compute a list of patches to turn text1 into text2. text2 is not provided,
   * diffs are the delta between text1 and text2.
   * 
   * @param text1 Old text.
   * @param diffs Array of diff tuples for text1 to text2.
   * @return LinkedList of Patch objects.
   */
  LinkedList<Patch> patch_make(String text1, LinkedList<Diff> diffs);

  /**
   * Given an array of patches, return another array that is identical.
   * 
   * @param patches Array of patch objects.
   * @return Array of patch objects.
   */
  LinkedList<Patch> patch_deepCopy(LinkedList<Patch> patches);

  /**
   * Merge a set of patches onto the text. Return a patched text, as well as an
   * array of true/false values indicating which patches were applied.
   * 
   * @param patches Array of patch objects
   * @param text Old text.
   * @return Two element Object array, containing the new text and an array of
   *         boolean values.
   */
  Object[] patch_apply(LinkedList<Patch> patches, String text);

  /**
   * Add some padding on text start and end so that edges can match something.
   * Intended to be called only from within patch_apply.
   * 
   * @param patches Array of patch objects.
   * @return The padding string added to each side.
   */
  String patch_addPadding(LinkedList<Patch> patches);

  /**
   * Look through the patches and break up any which are longer than the maximum
   * limit of the match algorithm. Intended to be called only from within
   * patch_apply.
   * 
   * @param patches LinkedList of Patch objects.
   */
  void patch_splitMax(LinkedList<Patch> patches);

  /**
   * Take a list of patches and return a textual representation.
   * 
   * @param patches List of Patch objects.
   * @return Text representation of patches.
   */
  String patch_toText(List<Patch> patches);

  /**
   * Parse a textual representation of patches and return a List of Patch
   * objects.
   * 
   * @param textline Text representation of patches.
   * @return List of Patch objects.
   * @throws IllegalArgumentException If invalid input.
   */
  List<Patch> patch_fromText(String textline) throws IllegalArgumentException;

  PatchResultOffset patch_apply_offsets(LinkedList<Patch> patches,
      CursorOffset cursorOffset, String text);

}